<?php
/**
 * @package mikrokosmos
 * mk script created on 17-feb-2006
 * jaco_at_pixeldump_dot_org
 */

if(!class_exists("MKTagHeader")){ class MKTagHeader {}}
if(!class_exists("MKSwfInspector")){ class MKSwfInspector {}}


/**
 * flasm object wrapper
 * it does a task mimic of flasm.exe
 * update, assemble, disassemble, compress, decompress
 */
class MKFlasm extends MKSwfInspector {

	var $swfDir = SERVER_MKFLASH;
	var $flasmDir = SERVER_MKCODE;
	var $backupDir = SERVER_MKBACKUP;
	var $swfFileName = "";
	var $flasmFileName = "";

	var $errorStatus = "";

	var $swfHeader;

	// the constructor
	function MKFlasm($swfFileName = "",
					  $flasmFileName = "",
					  $swfDir = SERVER_MKFLASH,
					  $flasmDir = SERVER_MKCODE){

		if(strlen($swfFileName)) $this->swfFileName = $swfFileName;
		if(strlen($flasmFileName)) $this->flasmFileName = $flasmFileName;

		if(file_exists($this->swfDir .$this->swfFileName)){
			parent::MKSwfInspector($this->swfFileName, $this->swfDir);
			if($this->get_isCompressed() == "yes") $this->decompress();
		}
		if(file_exists($this->flasmDir .$this->flasmFileName)){
			/* TODO: establishing task */
		}
	}

	//
	function set_swfDir($swfDir) {
		$this->swfDir = $swfDir;
		if(file_exists($this->swfDir .$this->swfFileName))
			parent::MKSwfInspector($this->swfFileName, $this->swfDir);
	}
	function get_swfDir() { return $this->swfDir; }

	//
	function set_flasmDir($flasmDir) { $this->flasmDir = $flasmDir; }
	function get_flasmDir() { return $this->flasmDir; }

	//
	function set_swfFileName($swfFileName) {
		$this->swfFileName = $swfFileName;
		if(file_exists($this->swfDir .$this->swfFileName))
			parent::MKSwfInspector($this->swfFileName, $this->swfDir);
	}
	function get_swfFileName() { return $this->swfFileName; }

	//
	function set_flasmFileName($flasmFileName) { $this->flasmFileName = $flasmFileName; }
	function get_flasmFileName() { return $this->flasmFileName; }

	//
	function get_swfHeader(){ return parent::fetch_assoc(); }

	//
	function refresh_swfData(){
		if(file_exists($this->swfDir .$this->swfFileName)){
			parent::MKSwfInspector($this->swfFileName, $this->swfDir);
		}
	}

	//
	function update(){ }

	//
	function assemble(){

		$swfPath = $this->swfDir .$this->swfFileName;
		$flasmPath = $this->flasmDir .$this->flasmFileName;

		if(!file_exists($swfPath))
			return $this->cast_error("ERROR: swf file not found!");

		if(!file_exists($flasmPath))
			return $this->cast_error("ERROR: flasm file not found!");

		/* TODO: implement assemble task */
	}

	//
	function disassemble($flasmFileOutput = false){

		if(!strlen($this->swfFileName) && !strlen($this->flasmFileName))
			return $this->cast_error("ERROR: no file given for disassembling");

		if(!strlen($this->flasmFileName))
			$this->flasmFileName = basename($this->swfFileName, ".swf") .".flm";

		$flasmPath = $this->flasmDir .$this->flasmFileName;

		if(!strlen($this->swfFileName))
			$this->swfFileName = basename($this->flasmFileName, ".flm") .".swf";

		$swfPath = $this->swfDir .$this->swfFileName;

		// this variable contains flasm syntax output
		$fStr = $this->fetch_flasm_header();
		$tagCount = $this->tagReport->get_tagCount();

		$protectID = get_tagID("Protect");

		$asTags = array($protectID,
						ACTIONS,
						MOVIECLIP,
						INITCLIP,
						LINKAGE,
						BUTTON2,
						PLACEOBJECT2);

		if($tagCount){

			$th = $this->tagReport->find_tagHeadersByTagID($asTags);

			$tCount = count($th);

			for($i = 0; $i < $tCount; $i++){

				$thAr = $th[$i];
				$tag = $this->get_tagByOffset($thAr["offset"]);
				$tagData = $tag->get_tagData();

				if($thAr["tagID"] == ACTIONS){
					$asc = new MKActionScriptContainer($tagData, $thAr["frame"]);
					$asc->disassemble();
					$fStr .= $asc->fetch_flasm(false);
				}
				else if($thAr["tagID"] == LINKAGE){
					$asc = new MKExportAssets($tagData, $thAr["frame"]);
					$fStr .= $asc->fetch_flasm();
				}
				else if($thAr["tagID"] == BUTTON2){
					$asc = new MKButtonContainer($tagData, $thAr["frame"]);
					$fStr .= $asc->fetch_flasm();
				}
				else if($thAr["tagID"] == PLACEOBJECT2 &&
						$thAr["poFlags"]["pfHasClipActions"]){
					$asc = new MKPlaceObject2($tagData);
					$fStr .= $asc->fetch_flasm();
				}
				else if($thAr["tagID"] == INITCLIP){
					$asc = new MKInitActionContainer($tagData, $thAr["frame"]);
					$asc->disassemble();
					$fStr .= $asc->fetch_flasm(false);
				}
				else if($thAr["tagID"] == $protectID){
					$asc = new MKProtect($tagData);

					$fStr .= "\r\n";
					$fStr .= "  protect '";
					$fStr .= $asc->get_MD5password();
					$fStr .= "'\r\n";
				}
				else if($thAr["tagID"] == MOVIECLIP){
					$mc = new MKMovieClip($tagData);

					$fStr .= "\r\n  defineMovieClip ";
					$fStr .= $mc->get_spriteID();
					$fStr .= " // total frames: ";
					$fStr .= $mc->get_frameCount();

					$mcTagReport = $mc->get_tagReport();
					$mcTagCount = $mcTagReport->get_tagCount();

					if($mcTagCount){

						$mcth = $mcTagReport->find_tagHeadersByTagID(array(ACTIONS, PLACEOBJECT2));
						$mctCount = count($mcth);

						if($mctCount){

							for($j = 0; $j < $mctCount; $j++){

								$mcthAr = $mcth[$j];

								$tag = $mc->get_tagByOffset($mcthAr["offset"]);

								$tagData = $tag->get_tagData();

								if($mcthAr["tagID"] == ACTIONS){
									$asc = new MKActionScriptContainer($tagData, $mcthAr["frame"]);
									$asc->disassemble();
									$fStr .= $asc->fetch_flasm(false, 2);
								}
								else if($mcthAr["tagID"] == PLACEOBJECT2 &&
										$mcthAr["poFlags"]["pfHasClipActions"]){
									$asc = new MKPlaceObject2($tagData);
									$fStr .= $asc->fetch_flasm();
								}
							}
						}
					}

					$fStr .= "\r\n  end // of defineMovieClip ";
					$fStr .= $mc->get_spriteID();
					$fStr .= "\r\n";

					if($flasmFileOutput){
						$flasmOut = fopen($this->flasmPath, "w");
						fwrite($flasmOut, $fStr, strlen($fStr));
						fclose($flasmOut);
					}
				}
			}

		}

		$fStr .= "end\r\n";

		return $fStr;
	}

	//
	function compress(){

		/* TODO: implement compress task */

		$swfPath = $this->swfDir .$this->swfFileName;

		if(!file_exists($swfPath))
			return $this->cast_error("ERROR: swf file not found!");

		$isCompressed = $this->isCompressed;

		if($isCompressed == "yes")
			return $this->cast_error("WARNING: swf is already compressed, nothing to be done");

		$swfFileSize = $this->swfFileSize;
		$swfHBuf = $this->swfHeaderBuf;

		if($this->isCompressed == "no"){

			$this->isCompressed = "yes";
			$swfHBuf[0] = "C";
			$backupPath = $this->swf_backup();

			$swfIn =  fopen($backupPath, "rb");
			$swfOut = fopen($swfPath, "wb");

			fseek($swfIn, 8, SEEK_SET);
			fwrite($swfOut, $swfHBuf, 8);
			$swfBody = fread($swfIn, $swfFileSize - 8);
			$gzData = gzcompress($swfBody, 9);
			fwrite($swfOut, $gzData, strlen($gzData));

			fclose($swfIn);
			fclose($swfOut);
		}
	}

	//
	function decompress(){

		$swfPath = $this->swfDir .$this->swfFileName;

		if(!file_exists($swfPath))
			return $this->cast_error("ERROR: swf file not found!");

		if($this->isCompressed == "no")
			return $this->cast_error("WARNING: swf is already decompressed, nothing to be done");

		$swfFileSize = $this->swfFileSize;
		$swfHBuf = $this->swfHeaderBuf;

		if($this->isCompressed == "yes"){

			$this->isCompressed = "no";
			$swfHBuf[0] = "F";
			$backupPath = $this->swf_backup();

			$swfIn =  fopen($backupPath, "rb");
			$swfOut = fopen($swfPath, "wb");

			fseek($swfIn, 8, SEEK_SET);
			fwrite($swfOut, $swfHBuf, 8);
			$gzData = fread($swfIn, $swfFileSize - 8);
			$swfBody = gzuncompress($gzData);
			fwrite($swfOut, $swfBody, strlen($swfBody));

			fclose($swfIn);
			fclose($swfOut);
		}
	}

		//
	function fetch_flasm_header(){

		$fStr = "movie '";
		$fStr .= "[omissis: absolute path] " .$this->swfFileName;
		//$fStr .= $this->swfDir . $this->swfFileName;
		$fStr .= "' // flash ";
		$fStr .= $this->swfVersion;
		$fStr .= ", total frames: " .$this->frameCount;
		$fStr .= ", frame rate: " .$this->fps;
		$fStr .= " fps, " .$this->stageWidth ."x";
		$fStr .= $this->stageHeight ." px\r\n";

		return $fStr;
	}

	//
	function swf_backup(){

		$swfPath = $this->swfDir .$this->swfFileName;

		$backupFileName = basename($this->swfFileName, ".swf") .".\$wf";
		$backupPath = $this->backupDir .$backupFileName;

		if(file_exists($backupPath)) unlink($backupPath);

		rename($swfPath, $backupPath);

		return $backupPath;
	}

	//
	function cast_error($msg){
		$this->errorStatus = $msg;
		return $this->errorStatus;
	}
}
?>
